package com.lazyframework.commons.util;

import java.io.*;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * 文件操作工具类
 * Create by lazy in 2019/10/29
 */
public class FileUtils {

    private static final String DEFAULT_COMPRESS_FORMAT = ".zip";

    private FileUtils() {}

    /**
     * 压缩文件
     * @param src 源文件
     * @param outPath 输出目录
     * @throws IOException
     */
    public static void compress(String src, String outPath) throws IOException {
        compress(src, outPath, DEFAULT_COMPRESS_FORMAT);
    }

    /**
     * 压缩文件
     * @param src 源文件
     * @param outPath 输出目录
     * @param format 压缩文件格式
     * @throws IOException
     */
    public static void compress(String src, String outPath, String format) throws IOException {
        File file = new File(src);
        String filename = file.getName(), compressFilename;

        // 得到压缩文件名称
        if (file.isDirectory()) {
            compressFilename = filename;
        } else {
            compressFilename = filename.substring(0, filename.lastIndexOf("."));
        }

        // 根据outPath和压缩文件名称创建Zip输出流
        String outFile = outPath + compressFilename + format;
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outFile));

        // 压缩
        if (file.isFile()) {
            compressFile(file, zos, filename);
        } else {
            compressDic(file, zos, filename);
        }

        // 压缩完成，释放资源
        zos.finish();
        zos.close();
    }

    /**
     * 解压缩
     * @param src
     * @param outPath
     * @throws IOException
     */
    public static void unCompress(String src, String outPath) throws IOException {
        File out = new File(outPath);
        if (!out.exists()) {
            out.mkdirs();
        }

        ZipEntry entry;
        ZipInputStream zis = new ZipInputStream(new FileInputStream(src));

        while ((entry = zis.getNextEntry()) != null) {
            String fileFullPath = entry.getName();
            if (entry.isDirectory()) {
                String fileDicPath = fileFullPath.substring(0, fileFullPath.lastIndexOf(File.separator));
                File outDic = new File(outPath + File.separator + fileDicPath);
                if (!outDic.exists()) {
                    outDic.mkdirs();
                }
            }
            File outFile = new File(outPath + File.separator + fileFullPath);

            try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outFile))) {
                int length;
                byte[] buffer = new byte[8192];
                while ((length = zis.read(buffer)) != -1)
                    bos.write(buffer, 0, length);
                bos.flush();
            }
        }

        zis.closeEntry();
        zis.close();
    }

    /**
     * 生成随机文件名称
     * @return
     */
    public static String generateRandomFilename(String originalFilename) {
        String suffix;
        if (originalFilename == null) {
            suffix = "";
        } else {
            int i = originalFilename.lastIndexOf(".");
            if (i != -1) {
                suffix = originalFilename.substring(i);
            } else {
                suffix = "";
            }
        }
        return UUID.randomUUID().toString().replace("-", "").toUpperCase() + suffix;
    }

    /**
     * 压缩文件夹
     * @param file
     * @param zos
     * @param entryName
     * @throws IOException
     */
    private static void compressDic(File file, ZipOutputStream zos, String entryName) throws IOException {
        if (file == null) {
            return;
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files == null) {
                return;
            }
            for (File f : files) {
                String nextEntryName = entryName + File.separator + f.getName();
                compressDic(f, zos, nextEntryName);
            }
        } else {
            compressFile(file, zos, entryName);
        }
    }

    /**
     * 压缩单个文件
     * @param file
     * @param zos
     * @param dic
     * @throws IOException
     */
    private static void compressFile(File file, ZipOutputStream zos, String dic) throws IOException {
        zos.putNextEntry(new ZipEntry(dic));
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        int length;
        byte[] buffer = new byte[8192];
        while ((length = bis.read(buffer)) > 0) {
            zos.write(buffer, 0, length);
        }
        zos.flush();
        bis.close();
    }

}
